package afcp.alumni.model;

import java.util.LinkedList;
import java.util.List;

import net.sourceforge.stripes.validation.ValidationErrors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import afcp.alumni.action.base.BaseAction;

public class SearchResult<T> {
	
	private static final Log logger = LogFactory.getLog(SearchResult.class);

	public SearchResult(int page, int perPage) {
		this.p = page;
		this.perPage = perPage;
//		this.locale = locale;
	}
	public SearchResult(long totalResults, int page, int perPage) {
		this.p = page;
		this.perPage = perPage;
//		this.locale = locale;
		setTotalResults(totalResults);
	}
//	public SearchResult(List<T> results, int page, int perPage) {
//		this.perPage = perPage;
//		this.addAll(results);
//	}

//	private Locale locale;
	private long totalResults;
	private int p;
	private int perPage;
	private int pMax;
	private boolean _hasResults;
	private boolean _hasNextPage;
	private boolean _hasPreviousPage;
	private int nextPage;
	private int previousPage;
	private List<T> list = new LinkedList<>();
	
	// for pagination urls
	private URL url;
	private String pageParam;
//	private Cursor cursor = null;

	public long getTotalResults() {
		return totalResults;
	}
	public int getPage() {
		return p;
	}
	public int getPerPage() {
		return perPage;
	}
	public int getpMax() {
		return pMax;
	}
	public boolean hasResults() {
		return _hasResults;
	}
	public boolean getHasNextPage() {
		return _hasNextPage;
	}
	public boolean getHasPreviousPage() {
		return _hasPreviousPage;
	}
	public int getNextPage() {
		return nextPage;
	}
	public int getPreviousPage() {
		return previousPage;
	}
	public List<T> getList() {
		return list;
	}
	public void setList(List<T> list) {
		this.list = list;
	}

//	public Cursor getCursor() {
//		return cursor;
//	}
//	public void setCursor(Cursor cursor) {
//		this.cursor = cursor;
//	}
	
//	public void calculateTotalResults() {
//		setTotalResults(size());
//	}

	public void setTotalResults(long totalResults) {
		this.totalResults = totalResults;
		try {
			pMax = (int) ((totalResults-1) / perPage + 1);
		} catch (ClassCastException e) {
			logger.warn("Could not cast the max page number from long to int. The max Integer value " + Integer.MAX_VALUE + " is used instead.", e);
			pMax = Integer.MAX_VALUE;
		}
		_hasNextPage = p < pMax || pMax == -1;
		_hasPreviousPage = p >= 2;
		_hasResults = totalResults > 0 && pMax != -1 && p >= 1 && p <= pMax;
		// set next page
		if (p >= pMax) {
			nextPage = pMax;
//			p = pMax;
		} else if (p < 1) {
				nextPage = 1;
		} else {
			nextPage = p+1;
		}
		// set previous page
		if (p <= 2) {
			previousPage = 1;
//			p = 1;
		} else if (p > pMax) {
			previousPage = pMax;
		} else {
			previousPage = p-1;
		}
	}

	
	public void checkPageValue(ValidationErrors errors) {
		// query is run before custom validation
		// check required page number
		if (p < 1) {
			BaseAction.addError(errors, "pagination.minvalue.valueBelowMinimum", 1);
		} else if (p > pMax) {
			BaseAction.addError(errors, "pagination.maxvalue.valueAboveMaximum", pMax);
		}
	}
	
	public void initPagination(URL currentPageUrl, String pageParam) {
		url = currentPageUrl;
		this.pageParam = pageParam;
	}

	// The following methods need initPagination() to be called first.
	
	public String getNextPageUrl() {
		url.addParam(pageParam, String.valueOf(getNextPage()));
		return url.getFullUrl();
	}
	public String getPreviousPageUrl() {
		url.addParam(pageParam, String.valueOf(getPreviousPage()));
		return url.getFullUrl();
	}
	
	public String toString() {
		return list.toString();
	}

}
